def insertFile(file_name, line_num, content, append=False):
    print("File %s, Line %d :\n %s" % (file_name, line_num, content))
    if 1:
        if append:
            with open(file_name, 'a') as file:
                file.write('\n' + content + '\n')
                print(f"Content '{content}' has been appended to the file")
                return
        else:
            s = []
            with open(file_name, "r") as in_file:
                for lines in in_file:
                    s.append(lines)
            s.insert(line_num, content)
            temp = "".join(s)
            with open(file_name, "w") as out_file:
                out_file.write(temp)
            return


def findLine(file_name, content, skip):
    s = []
    count = 0
    skip_count = 0
    with open(file_name, "r") as in_file:
        for lines in in_file:
            count = count + 1
            if content in lines:
                if count > skip :
                    print("find line %s %d" % (content, count))
                    return count - 1
    print("not find line %s %d" % (content, count))
    return -1

VAR_DICT = {"double": "d", "float": "d", "int": "i", "short": "i", "long": "i", "unsigned char" : 'c', 'char' : 'c'} #python 参数解析用


class VARIABLE:
    v_name = "unkown"
    v_type = "unkonw"
    v_dim = 1

    def __init__(self, name, type, dim):
        self.v_name = name
        self.v_type = type
        self.v_dim = dim


# 1.0 define the compoent of the interface
PATH = "./"
type_key = "SET"  # 接口的类型
key_words = ["sim", "robot"]  #, "stop", "pos"]  # 接口的主要信息
variable = [
    VARIABLE("sim_serial_num", "int", 1),
    
]

#     VARIABLE("friction_identify_start_pos", "double", 6),
# ]  # 接口的数据结构
usersetting_zone = ""  # 配置文件的域名
need_save = False

# 2.0 generate the variable name
if type_key == "START" or type_key == "STOP":
    ZUC_NML_CLASS = "ZUC_" + type_key + "_" + "_".join(
        key_words).upper()  # python 与 任务层的数据结构
else:
    ZUC_NML_CLASS = "ZUC_" + type_key + "_" +  "_".join(key_words).upper()  # python 与 任务层的数据结构

ZUC_NML_TYPE = "%s_TYPE" % (ZUC_NML_CLASS)  # 任务层的数据结构标示

ZUCMODULE_FUNC = "robot_" + type_key.lower() + "_" + "_".join(key_words)  # 任务层主函数名

MOTION_COMMAND_STRUCT = "zuc_%s_t" % (type_key.lower() + "_" + "_".join(key_words))  # 实时层指令数据结构

MOTION_COMMAND_TYPE = "ZUCMOT_%s_%s" % (type_key, "_".join(key_words).upper()
                                        )  # 实时层指令标示

if type_key == "START" or type_key == "STOP":
    MOTION_COMMAND_STRUCT_VAR = type_key.lower() + "".join(
        key_words)  # 任务层与实时层数据名
else:
    MOTION_COMMAND_STRUCT_VAR = "".join(key_words)  # 任务层与实时层数据名

for i in range(len(key_words)):
    key_words[i] = key_words[i].capitalize()

TASKINTF_FUNC = "zuc" + type_key.capitalize() + "".join(key_words)  # 任务层次级函数名
CMD_CLASS = "Cmd" + type_key.capitalize() + "".join(key_words)  # command 类

INITRAJ_SAVE_FUNC = "iniSave" + "".join(key_words)  # 写入配置文件函数
INITRAJ_LOAD_FUNC = "init" + "".join(key_words)  # 加载配置文件函数
key_words[0] = key_words[0].lower()  # 任务层与实时层数据名
MOTION_COMMAND_STRUCT_VAR_VAR = "".join(key_words)  # 实时层指令数据变量名

# zuc_nml.hh && zuc.hh && zuc.cc

######################################################################### zuc_nml.hh 定义python调用层的数据结构
zuc_module_class_variable_def = ""
for x in variable:
    if x.v_dim == 1:
        zuc_module_class_variable_def += x.v_type + " " + x.v_name + ";"
    else:
        zuc_module_class_variable_def += x.v_type + " " + x.v_name + "[" + str(x.v_dim) + "]" + ";"
zuc_module_class_variable_def = zuc_module_class_variable_def.strip(";")

if len(variable) == 0:
    zuc_module_class = "DEC_CMD_P0(%s);" % (ZUC_NML_CLASS)
else:
    zuc_module_class = "DEC_CMD_PN(%s, %s);" % (ZUC_NML_CLASS, zuc_module_class_variable_def)

file = PATH + "/src/zuc/nml_intf/" + "zuc_nml_rob_cmd.hh"
# line = findLine(
#     file, "DEC_CMD_P0(ZUC_CONVEYOR_DISABLE);\n", 0)
# if line == -1:
#     line = 403
insertFile(file, -1, zuc_module_class, True)    #插入末尾
##########################################################################

# # zuc.hh 定义python调用层的指令类型
# zuc_nml_define = "#define %s                    ((NMLTYPE) 59)\n" % (
#     ZUC_NML_TYPE)  # the number should be changed
# file = PATH + "/src/zuc/nml_intf/" + "zuc.hh"
# line = findLine(
#     file, "#define ZUC_TASK_START_DYNAMICS_IDENTIFY_TYPE ((NMLTYPE)610)\n", 0)
# if line == -1:
#     line = 285
# insertFile(file, line, zuc_nml_define)

#############################################################################
# 更新内存 zuc.cc
zuc_update = f"ZUC_CMD_FORMAT({ZUC_NML_CLASS})\n"
line = 344
file = PATH + "/src/zuc/nml_intf/" + "zuc.cc"
line = findLine(file, "    default:\n", 0)
if line == -1:
    line = 243
insertFile(file, line, zuc_update)

#############################################################################
# 更新内存 zuc_nml_rob_cmd.cc
zuc_update_data = ""
for x in variable:
    if x.v_dim == 1:
        zuc_update_data += f"cms->update({x.v_name});\n"
    else:
        zuc_update_data += f"cms->update({x.v_name},{x.v_dim});\n"

zuc_update_func = f"void {ZUC_NML_CLASS}::update_param(CMS* cms)\n" + \
"{\n" + \
f"{zuc_update_data}" + \
"}\n"
file = PATH + "/src/zuc/nml_intf/" + "zuc_nml_rob_cmd.cc"
insertFile(file, -1, zuc_update_func, True)

#############################################################################
# "zucmodule_cmd.cc"
zuc_module_variable_type = ""
for x in variable:
    for i in range(0, x.v_dim):
        zuc_module_variable_type += VAR_DICT[x.v_type]
zuc_module_variable_assign = ""
for x in variable:
    if x.v_dim == 1:
        zuc_module_variable_assign += "&m." + x.v_name + ", "
    else:
        for i in range(0, x.v_dim):
            zuc_module_variable_assign += "&m." + x.v_name + "[" + str(
                i) + "]" + ", "
zuc_module_variable_assign = zuc_module_variable_assign.strip(", ")

zuc_module_interface = \
"static PyObject *%s(pyCommandChannel *s, PyObject *o)\n\
{\n\
    %s m;\n\
	if(!PyArg_ParseTuple(o, \"i%s\", &m.robot_id, %s))\n\
        return NULL;\n\
    \n\
    zucSendCommand(s, m);\n\
    Py_INCREF(Py_None);\n\
    return Py_None;\n\
}\n\n" % (ZUCMODULE_FUNC, ZUC_NML_CLASS, zuc_module_variable_type, zuc_module_variable_assign)

file = PATH + "/src/zuc/usr_intf/axis/extensions/" + "zucmodule_cmd.cc"
line = findLine(
    file,
    "static PyObject* robot_jog_multi_joint(pyCommandChannel* s, PyObject* o)\n",
    0)
if line == -1:
    line = 4295
insertFile(file, line, zuc_module_interface)

# "zucmodule_cmd.cc"
interface_active = "    {\"%s\", (PyCFunction)%s, METH_VARARGS},\n" % (ZUCMODULE_FUNC, ZUCMODULE_FUNC)
skip_line = findLine(file,
    "static PyMethodDef Command_methods[] = {{\"setCabVoltage\", (PyCFunction)setCabVoltage, METH_VARARGS},\n",
    0)
line = findLine(file,
    "                                        {NULL}};",
    skip_line)
if line == -1:
    line = 6554
insertFile(file, line, interface_active)

#####################################################################################
# "zuc.hh"
taskintf_variable = ""
for x in variable:
    if x.v_dim == 1:
        taskintf_variable += x.v_type + " " + x.v_name + ", "
    else:
        taskintf_variable += "const " + x.v_type + "* " + x.v_name + ", "
taskintf_variable = taskintf_variable.strip(", ")
if need_save:
    taskintf_func_def = f"extern int {TASKINTF_FUNC}(int robot_id, {taskintf_variable}, int saveOpt);\n"
else:
    taskintf_func_def = f"extern int {TASKINTF_FUNC}(int robot_id, {taskintf_variable});\n"
file = PATH + "/src/zuc/nml_intf/" + "zuc.hh"
insertFile(file, line, taskintf_func_def, True)


type_def = f"#define {ZUC_NML_TYPE}        ZUC_ROB_MOVING_CMD(13)\n"
line = findLine(file,
    "#define ZUC_JOG_MULTI_JOINT_TYPE        ZUC_ROB_MOVING_CMD(13)\n",
    0)
insertFile(file, line, type_def)


#######################################################################################################
# moving_cmd.hh
class_variable_def = ""
for x in variable:
    if x.v_dim == 1:
        class_variable_def += x.v_type + " " + x.v_name + "_;"
    else:
        class_variable_def += x.v_type + " " + x.v_name + "_[" + str(x.v_dim) + "]" + ";"
taskintf_variable_assign = ""
for x in variable:
    if x.v_dim == 1:
        taskintf_variable_assign += x.v_name + "_ = " + x.v_name + ";\n"
    else:
        taskintf_variable_assign += "\tfor (" + "int i = 0; i < " + str(
            x.v_dim) + "; i++) {\n"
        taskintf_variable_assign += "\t\t" + x.v_name + "_[i]" + " = " + x.v_name + "[i];\n"
        taskintf_variable_assign += "\t}\n"
cmd_class_def = f"\nclass {CMD_CLASS} : public mot::MultiRobCmd\n" + \
"{\n\
public:\n" + \
f"    {CMD_CLASS}(int grp_id, {taskintf_variable})\n" + \
"    {\n\
        group_id_ = grp_id;\n" + \
f"{taskintf_variable_assign}" + \
f"        cmd_name_ = MOTION_CMD_CLASS_NAME({CMD_CLASS});\n" + \
"    };\n" + \
f"    ~{CMD_CLASS}()" + " {}\n" + \
"\n\
    virtual int active_callback() { return 0; };\n\
    virtual int process();\n\
    virtual int check_para() { return 0; };\n\
    %s\n\
};" % (class_variable_def)

file = PATH + "/src/zuc/motion/motion_cmd/" + "motion_cmd.h"
insertFile(file, line, cmd_class_def, True)

#######################################################################################################
# moving_cmd.cc
class_process = f"\nint {CMD_CLASS}::process()\n" + \
"{\n\
    auto robot = axisgroup::AxisGroupMgr::instance().get_axisgroup(group_id_);\n\
    return 0;\n\
}\n"
file = PATH + "/src/zuc/motion/motion_cmd/" + "motion_cmd.cc"
insertFile(file, line, class_process, True)

#########################################################################################################
# taskintf_multi.cc
variable_def = ""
for x in variable:
        variable_def += x.v_name + ","
variable_def = variable_def.strip(",")
taskintf_func = taskintf_func_def.replace("extern", "")
taskintf_func = taskintf_func.replace(";\n", "\n")
task_imply = f"\n{taskintf_func}" + \
"{\n" + \
f"    auto cmd = std::make_shared<{CMD_CLASS}>(robot_id, {variable_def});\n" + \
"    return mot::realtime_cmd_call(cmd);\n\
}\n"
file = PATH + "/src/zuc/task/" + "taskintf_multirobot.cc"
insertFile(file, line, task_imply, True)

###################################################################
# zuctaskmain.cc interface
zuc_stak_vraiable_assign = ""
for x in variable:
    zuc_stak_vraiable_assign += "task_cmd->" + x.v_name + ", "
zuc_stak_vraiable_assign = zuc_stak_vraiable_assign.strip(", ")

if need_save:
    zuctaskmain_case_action = \
    "	case %s: {\n\
            %s *task_cmd = (%s * ) cmd;\n\
            %s(task_cmd->robot_id, %s, 1);\n\
            break;\n\
        }\n\n" % (ZUC_NML_TYPE, ZUC_NML_CLASS, ZUC_NML_CLASS, TASKINTF_FUNC, zuc_stak_vraiable_assign)
else:
    zuctaskmain_case_action = \
    "	case %s: {\n\
            %s *task_cmd = (%s * ) cmd;\n\
            %s(task_cmd->robot_id, %s);\n\
            break;\n\
        }\n\n" % (ZUC_NML_TYPE, ZUC_NML_CLASS, ZUC_NML_CLASS, TASKINTF_FUNC, zuc_stak_vraiable_assign)

zuctaskmain_case = "\tcase %s:\n" % (ZUC_NML_TYPE)
# print("File zuctaskmain.cc, Line 2745\n %s" % zuctaskmain_case_action)
line = 2745
file = PATH + "/src/zuc/task/" + "zuctaskmain.cc"
skip_line = findLine(file, "static int zucTaskIssueCommand(NMLmsg* cmd)", 0)
line = findLine(file, "    default:  // unrecognized command", 0)
insertFile(file, line, zuctaskmain_case_action)

# # print("File zuctaskmain.cc, Line 1005\n %s" % zuctaskmain_case)
# line = 930
# file = PATH + "/src/zuc/task/" + "zuctaskmain.cc"
# line = findLine(file, "    case ZUC_IDENTIFY_CYCLE_TIME_TYPE:\n", 0)
# if line == -1:
#     line = 3205
# insertFile(file, line, zuctaskmain_case)
# # print("File zuctaskmain.cc, Line 930\n %s" % zuctaskmain_case)
# line = 1005
# file = PATH + "/src/zuc/task/" + "zuctaskmain.cc"
# line = findLine(file,
#                 "            case ZUC_TASK_START_DYNAMICS_IDENTIFY_TYPE:\n", 0)
# if line == -1:
#     line = 3205
# insertFile(file, line, "\t\t" + zuctaskmain_case)
# # print("File zuctaskmain.cc, Line 1179\n %s" % zuctaskmain_case)


